package com.tl.boot.main.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.tl.boot.common.enums.LocalDataBaseEnum;
import com.tl.boot.common.utils.LogUtil;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * com.tl.boot.main.datasource -- DynamicDataSourceConfig
 * Description:
 * Created by joshua_liu <a href="mailto:joshualwork@163.com"></a>
 * On 2019/9/24 17:34
 */
@Configuration
@MapperScan({"com.tl.boot.mapper.**"})
public class DynamicDataSourceConfig {

    @Bean(name = "primaryDruid")
    @ConfigurationProperties(prefix = "spring.datasource.config.primaryDruid")
    public DruidConfig primaryDruid() {
        return new DruidConfig();
    }

    @Bean(name = "secondaryDruid")
    @ConfigurationProperties(prefix = "spring.datasource.config.secondaryDruid")
    public DruidConfig secondaryDruid() {
        return new DruidConfig();
    }

    @Bean(name = "currentDruidConfig")
    public DruidConfig currentDruidConfig(
            @Qualifier("primaryDruid") DruidConfig druidConfig1,
            @Qualifier("secondaryDruid") DruidConfig druidConfig2) {
        LocalDataBaseEnum dataBaseType = DataSourceType.getDataBaseType();
        switch (dataBaseType) {
            case PRIMARY_DRUID:
                return druidConfig1;
            case SECONDARY_DRUID:
                return druidConfig2;
            default:
                return druidConfig1;

        }
    }

    @Bean(name = "primaryDruidDataSource")
    public DataSource primaryDruidDataSource(@Qualifier("primaryDruid") DruidConfig config) {
        DataSource dataSource = druidDataSourceInit(config);
        return dataSource;
    }

    @Bean(name = "dynamicTxManager")
    public DataSourceTransactionManager primaryDruidDataSourceTransactionManager(
            @Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    @Bean(name = "secondaryDruidDataSource")
    public DataSource secondaryDruidDataSource(@Qualifier("secondaryDruid") DruidConfig config) {
        return druidDataSourceInit(config);
    }

    //配置druid访问资源页面servlet
    @Bean
    public ServletRegistrationBean druidStatViewServlet(@Qualifier("currentDruidConfig") DruidConfig config) {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");

        if (config.getDruidAllowIp() != null) {
            registrationBean.addInitParameter("allow", config.getDruidAllowIp());
        }

        if (config.getDruidDenyIp() != null) {
            registrationBean.addInitParameter("deny", config.getDruidDenyIp());
        }

        registrationBean.addInitParameter("loginUsername", config.getDruidLoginAccount());
        registrationBean.addInitParameter("loginPassword", config.getDruidLoginPassword());
        registrationBean.addInitParameter("resetEnable", config.isResetEnable() ? "true" : "false");
        return registrationBean;
    }

    @Bean
    //配置druid过滤器 默认通过http://localhost:1000/bootFirst/druid/login.html 页面进行访问
    public FilterRegistrationBean druidWebStatViewFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new WebStatFilter());
        registrationBean.addInitParameter("urlPatterns", "/*");
        registrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
        return registrationBean;
    }


    @Bean(name = "dynamicDataSource")
    public DynamicDataSource DataSource(@Qualifier("primaryDruidDataSource") DataSource primaryDruidDataSource,
                                        @Qualifier("secondaryDruidDataSource") DataSource secondaryDruidDataSource) {

        //这个地方是比较核心的targetDataSource 集合是我们数据库和名字之间的映射
        Map<Object, Object> targetDataSource = new HashMap<>();
        targetDataSource.put(LocalDataBaseEnum.PRIMARY_DRUID, primaryDruidDataSource);
        targetDataSource.put(LocalDataBaseEnum.SECONDARY_DRUID, secondaryDruidDataSource);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSource);
        dataSource.setDefaultTargetDataSource(primaryDruidDataSource);//设置默认对象
        return dataSource;
    }

    @Bean(name = "mybatisConfiguration")
    @ConfigurationProperties(prefix = "mybatis.configuration")
    public org.apache.ibatis.session.Configuration mybatisConfiguration() {
        return new org.apache.ibatis.session.Configuration();
    }
    @Bean(name = "SqlSessionFactory")
    public SqlSessionFactory SqlSessionFactory(
            @Qualifier("dynamicDataSource") DataSource dynamicDataSource,
            @Qualifier("mybatisConfiguration") org.apache.ibatis.session.Configuration mybatisConfiguration)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setConfiguration(mybatisConfiguration);
        bean.setDataSource(dynamicDataSource);
        //设置我们的xml文件路径
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().
                        getResources("classpath*:com/*/*.xml"));
        return bean.getObject();
    }

    private DataSource druidDataSourceInit(DruidConfig config) {
        DruidDataSource dataSource = new DruidDataSource();
        /*数据源主要配置*/
        dataSource.setUrl(config.getUrl());
        dataSource.setDriverClassName(config.getDriverClassName());
        dataSource.setUsername(config.getUsername());
        dataSource.setPassword(config.getPassword());

        /*数据源补充配置*/
        dataSource.setMaxActive(config.getMaxActive());
        dataSource.setInitialSize(config.getInitialSize());
        dataSource.setMinIdle(config.getMinIdle());
        dataSource.setMaxWait(config.getMaxWait());
        dataSource.setTimeBetweenEvictionRunsMillis(config.getTimeBetweenEvictionRunsMillis());
        dataSource.setMinEvictableIdleTimeMillis(config.getMinEvictableIdleTimeMillis());
        dataSource.setPoolPreparedStatements(config.isPoolPreparedStatements());
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.getMaxPoolPreparedStatementPerConnectionSize());
        dataSource.setConnectionProperties(config.getConnectionProperties());
        dataSource.setUseGlobalDataSourceStat(config.isUseGlobalDataSourceStat());

        try {
            dataSource.setFilters(config.getFilters());
            LogUtil.info("Druid数据源初始化设置成功......");
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.error("Druid数据源初始化设置失败......");
        }
        return dataSource;

    }
}
